nav: band the session list by status, then by created_at, so rows stop leapfrogging - #95
Open
ellipsis-dev[bot] wants to merge 1 commit into
Open
nav: band the session list by status, then by created_at, so rows stop leapfrogging#95ellipsis-dev[bot] wants to merge 1 commit into
ellipsis-dev[bot] wants to merge 1 commit into
Conversation
The bottom session nav sorted by last event (open conversations first, then most-recent-event first). With several sessions in flight that means every agent response is a new event, so the list permuted on every poll and the row you were reading walked out from under you. Sort by status band, then newest-born first inside a band: 0 live — waiting / working / starting / scheduled / retrying 1 parked — sleeping / idle 2 done — completed / closed 3 dead — error / failed / stopped / cancelled `waiting` shares the live band with the in-flight statuses deliberately: a warm session crosses working -> waiting -> working on every turn, so banding those apart would reproduce the churn this change exists to remove. created_at is fixed for the life of a session, so a row only moves when it truly changes band. Drops isOpenConversation, whose only caller was the old sort. Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The session nav — the bottom band of the multi-session TUI that a bare
agent,agent "prompt", andagent session connect <id>all open — sorted open conversations first, then most-recent-event first:lastEventAtreadslast_activity_at, which ticks on every agent response. With several sessions in flight, each poll hands the nav a differently-permuted list: rows leapfrog continuously and the row you were reading walks out from under the cursor. The highlight itself is tracked by id, not index, so the cursor does follow its session — but the list under it keeps moving, which is the part that reads as broken.The change
Two keys: a status band, then
created_atdescending inside the band.waiting,working,starting,scheduled,retrying(+ rawrunning,creating_sandbox)sleeping,idlecompleted,closed, and anything unrecognizederror,failed,stopped,cancelledTwo properties make this actually stop the churn:
created_atis immutable. Nothing an agent does changes it, so within a band the order is fixed for the life of every row.waitingshares band 0 with the in-flight words. This is the load-bearing bit: a warm session crossesworking → waiting → workingon every turn (both project fromAgentSessionStatus.RUNNING, split only by whether a turn is open). A band boundary there would have reproduced exactly the per-response reordering this change exists to remove. Both words mean "this conversation is live"; which side of a turn it sits on is the dot's job, not the row's position.A row therefore moves only when a conversation genuinely parks, finishes, or dies — a handful of times per session, not once per turn.
Banding keys off
rowStatusWord(the server'ssurface.statusprojection, with rawstatusas the fallback for pre-surface servers).isOpenConversationis dropped — the old sort was its only caller.Note the row's age tag still counts from
lastEventAt, so recency is still visible; it just no longer drives position.Verification
Full CI equivalent locally on this branch —
typecheck,test,build, and the--compilebinary smoke all clean:The rewritten tests assert band order, that a chatty-but-older session does not out-rank a younger one, and that flipping two live rows between
workingandwaitingleaves the order byte-identical — the regression that would catch a future re-split of band 0.Confirmed these are genuine regression tests rather than just coverage: swapping only
sortSidebarSessions' body back to the old recency logic (keeping the new exports, so the failure is behavioural and not a missing import) fails 3 of them, includingexpected [ 'old', 'fresh' ] to deeply equal [ 'fresh', 'old' ]— the reported churn, reproduced.Also checked the blast radius:
sortSidebarSessionsis reachable only viamergeSidebarSessions→ the TUI nav, soagent session listis unaffected, and nothing indocs/orskills/describes the old ordering.Provenance
Written and verified in an Ellipsis sandbox that was read-only on this repo, so it was parked in the monorepo as a handoff doc in ellipsis-dev/ellipsis#6046. This PR is that patch applied via
git am(clean, no fuzz) and re-verified from scratch. Note it was authored against an olderclibase — main has since moved 2 commits (#93, #94), hence 409 tests here versus the 390 the doc recorded. #6046 is being closed in favour of this PR.🤖 Generated with Claude Code